
/****************************************************************************
    Header files
*/
#include "a2dp.h"
#include "a2dp_private.h"
#include "a2dp_caps_parse.h"
#ifdef ENABLE_LDAC_SINK
#include "a2dp_codec_sony_ldac.h"

#ifdef A2DP_DEBUG_LIB
#include <stdlib.h>
#include <string.h>
#include <print.h>
#endif

/*************************************************************************/

/*
 non A2DP Codec Specific Infomation Elements for LDAC

                  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
  service_caps[4] |   SONY ID                                     | Octet0
  service_caps[5] |   SONY ID                                     | Octet1
  service_caps[6] |   SONY ID                                     | Octet2
  service_caps[7] |   SONY ID                                     | Octet3
  service_caps[8] |   SONY Specific Codec ID                      | Octet4
  service_caps[9] |   SONY Specific Codec ID                      | Octet5
  service_caps[A] |   RFA     |   Sampling Frequency              | Octet6
  service_caps[B] |   RFA                       | Channel Mode ID | Octet7
*/
#define LDAC_MEDIA_CODEC_SC_SIZE         (10+2)

/*! [Octet 0-3] Vendor ID of SONY */
#define LDAC_VENDOR_ID0 0x2D
#define LDAC_VENDOR_ID1 0x01
#define LDAC_VENDOR_ID2 0x0
#define LDAC_VENDOR_ID3 0x0

/*! [Octet 4-5] Vendor Specific Codec ID of LDAC */
#define LDAC_VENDOR_CODEC_ID0 0xAA
#define LDAC_VENDOR_CODEC_ID1 0x00

/*
 <Octet 6>
  * Specific Codec Value *
  * Fs [b5-b0] *
     |  5  |  4  |  3  |  2  |  1  |  0  |
     |  o  |     |     |     |     |     |  44100
     |     |  o  |     |     |     |     |  48000
     |     |     |  o  |     |     |     |  88200
     |     |     |     |  o  |     |     |  96000
     |     |     |     |     |  o  |     | 176400
     |     |     |     |     |     |  o  | 192000
*/
/*! [Octet 6] Support for 44.1kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_044100        0x20
/*! [Octet 6] Support for 48kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_048000        0x10
/*! [Octet 6] Support for 88.2kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_088200        0x08
/*! [Octet 6] Support for 96kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_096000        0x04
/*! [Octet 6] Support for 176.4kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_176400        0x02
/*! [Octet 6] Support for 192kHz sampling frequency */
#define LDAC_SAMPLING_FREQ_192000        0x01

/*
 <Octet 7>
  * channel mode <b2-b0> *
     |  2  |  1  |  0  |
     |  o  |     |     | MONO
     |     |  o  |     | DUAL CHANNEL
     |     |     |  o  | STEREO
*/
/*! [Octet 7] Support for MONO */
#define LDAC_CHANNEL_MODE_MONO           0x04
/*! [Octet 7] Support for DUAL CHANNEL */
#define LDAC_CHANNEL_MODE_DUAL_CHANNEL   0x02
/*! [Octet 7] Support for STEREO */
#define LDAC_CHANNEL_MODE_STEREO         0x01

void getSonyLdacConfigSettings(const uint8 *service_caps, a2dp_codec_settings *codec_settings)
{
	int val;
    uint32 fs, cm;
#ifdef A2DP_DEBUG_LIB
    PRINT(( "%4d@%s\n", __LINE__, "getSonyLdacConfigSettings"/*__FUNCTION__*/ ));
#endif

    fs = (uint32)(2*48000);
    cm = LDAC_CHANNEL_MODE_STEREO;
    if (service_caps)
    {
        /* get sampling frequency */
        val = (int)service_caps[10];
        if(0){;}
        /*else if( val & LDAC_SAMPLING_FREQ_192000 ){ fs = (uint32)(4*48000);}*//* 192khz */
        /*else if( val & LDAC_SAMPLING_FREQ_176400 ){ fs = (uint32)(4*44100);}*//* 176.4khz */
        else if( val & LDAC_SAMPLING_FREQ_096000 ){ fs = (uint32)(2*48000);}/* 96khz */
        else if( val & LDAC_SAMPLING_FREQ_088200 ){ fs = (uint32)(2*44100);}/* 88.2khz */
        else if( val & LDAC_SAMPLING_FREQ_048000 ){ fs = (uint32)(48000);}
        else if( val & LDAC_SAMPLING_FREQ_044100 ){ fs = (uint32)(44100);}
        else{
#ifdef A2DP_DEBUG_LIB
            PRINT(( "%4d@%s Error: Unsupported FS INFO 0x%02x!\n", __LINE__, "getSonyLdacConfigSettings"/*__FUNCTION__*/, val ));
#endif
        }

        /* get channel mode */
        val = (int)service_caps[11];
        if(0){;}
        else if( val & LDAC_CHANNEL_MODE_STEREO ){       cm = LDAC_CHANNEL_MODE_STEREO;}
        else if( val & LDAC_CHANNEL_MODE_DUAL_CHANNEL ){ cm = LDAC_CHANNEL_MODE_DUAL_CHANNEL;}
        else if( val & LDAC_CHANNEL_MODE_MONO ){         cm = LDAC_CHANNEL_MODE_MONO;}
        else{
#ifdef A2DP_DEBUG_LIB
            PRINT(( "%4d@%s Error: Unsupported Channel Mode 0x%02x\n", __LINE__, "getSonyLdacConfigSettings"/*__FUNCTION__*/, val ));
#endif
        }
    }

    codec_settings->codecData.ldac_params.sampling_frequency = codec_settings->rate = fs;
    codec_settings->codecData.ldac_params.channel_mode = cm;

    /* set a2dp channel mode */
    switch(cm){
        case LDAC_CHANNEL_MODE_STEREO:
            codec_settings->channel_mode = a2dp_stereo;
            break;
        case LDAC_CHANNEL_MODE_DUAL_CHANNEL:
            codec_settings->channel_mode = a2dp_dual_channel;
            break;
        case LDAC_CHANNEL_MODE_MONO:
            codec_settings->channel_mode = a2dp_mono;
            break;
    }

#ifdef A2DP_DEBUG_LIB
    PRINT(( "%4d@%s rate:%u (0x%08x), LDAC cm:%d\n", __LINE__, "getSonyLdacConfigSettings"/*__FUNCTION__*/, (unsigned int)fs, (unsigned int)fs, (int)cm ));
#endif
}


/**************************************************************************/
void selectOptimalSonyLdacCapsSink(const uint8 *local_codec_caps, uint8 *remote_codec_caps)
{
    uint8 val;

#ifdef A2DP_DEBUG_LIB
    PRINT(( "%4d@%s\n", __LINE__, "selectOptimalSonyLdacCapsSink"/*__FUNCTION__*/ ));
#endif
    /* Select sample frequency */
	val = (local_codec_caps[10]) & (remote_codec_caps[10]);
#ifdef A2DP_DEBUG_LIB
    PRINT(( "%4d@%s rate_id:0x%02x\n", __LINE__, "selectOptimalSonyLdacCapsSink"/*__FUNCTION__*/, val ));
#endif
	if( 0 ){;}
	/*else if( val & LDAC_SAMPLING_FREQ_192000 ){ val = LDAC_SAMPLING_FREQ_192000; }*/
	/*else if( val & LDAC_SAMPLING_FREQ_176400 ){ val = LDAC_SAMPLING_FREQ_176400; }*/
	else if( val & LDAC_SAMPLING_FREQ_096000 ){ val = LDAC_SAMPLING_FREQ_096000; }
	else if( val & LDAC_SAMPLING_FREQ_088200 ){ val = LDAC_SAMPLING_FREQ_088200; }
	else if( val & LDAC_SAMPLING_FREQ_048000 ){ val = LDAC_SAMPLING_FREQ_048000; }
	else if( val & LDAC_SAMPLING_FREQ_044100 ){ val = LDAC_SAMPLING_FREQ_044100; }
	else { val = LDAC_SAMPLING_FREQ_096000; }
	remote_codec_caps[10] = val;

	/* channel mode */
	val = (local_codec_caps[11]) & (remote_codec_caps[11]);
	if(0){;}
	else if( val & LDAC_CHANNEL_MODE_STEREO ){       val = LDAC_CHANNEL_MODE_STEREO;}
	else if( val & LDAC_CHANNEL_MODE_DUAL_CHANNEL ){ val = LDAC_CHANNEL_MODE_DUAL_CHANNEL;}
	else if( val & LDAC_CHANNEL_MODE_MONO ){         val = LDAC_CHANNEL_MODE_MONO;}
	else{ val = LDAC_CHANNEL_MODE_STEREO; }
	remote_codec_caps[11] = val;

#ifdef A2DP_DEBUG_LIB
    PRINT(( "%4d@%s fs:0x%02x, cm:0x%x\n", __LINE__, "selectOptimalSonyLdacCapsSink"/*__FUNCTION__*/, (int)remote_codec_caps[10], (int)remote_codec_caps[11] ));
#endif
}

#endif /* ENABLE_LDAC_SINK */
